package id.co.rho.scoring.cid.changecontrol.entitychange;

import id.co.rho.scoring.cid.changecontrol.entitychange.propertychange.PropertyChange;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

// TODO change to EntityChange
public class UpdateEntityChange implements EntityChange, Serializable {
	private String entityType;
	private Serializable entityId;
    private boolean newEntity;
    private boolean deleteEntity;
	/**
	 * Map<nama property, instance PropertyChange>
	 */
	private HashMap<String,PropertyChange> propertyChanges = new HashMap<String, PropertyChange>();

    private HashMap<String,Serializable> metadata = new HashMap<String, Serializable>();
	
	public UpdateEntityChange() {
		super();
	}

	public UpdateEntityChange(String entityType, Serializable entityId) {
		super();
		this.entityType = entityType;
		this.entityId = entityId;
	}

	public String getEntityType() {
		return entityType;
	}

	public void setEntityType(String entityType) {
		this.entityType = entityType;
	}

	public Serializable getEntityId() {
		return entityId;
	}

	public void setEntityId(Serializable entityId) {
		this.entityId = entityId;
	}

    public boolean isNewEntity() {
        return newEntity;
    }

    public void setNewEntity(boolean newEntity) {
        this.newEntity = newEntity;
    }

    public boolean isDeleteEntity() {
        return deleteEntity;
    }

    public void setDeleteEntity(boolean deleteEntity) {
        this.deleteEntity = deleteEntity;
    }

    public List<PropertyChange> getPropertyChanges() {
		return new LinkedList(propertyChanges.values());
	}
	
	public void recordChange(String propertyName, Serializable oldValue, Serializable newValue) {
		PropertyChange propChange = propertyChanges.get(propertyName);
		if(propChange==null) {
			propChange = new PropertyChange(propertyName,oldValue,newValue);
			propertyChanges.put(propertyName, propChange);
		}else {
			propChange.setNewValue(newValue);
		}
	}
	
	public boolean removeRecordedChange(String propertyName) {
		return propertyChanges.remove(propertyName) != null;
	}

	public PropertyChange getRecordedChange(String propertyName) {
		return propertyChanges.get(propertyName);
	}

    public HashMap<String, Serializable> getMetadata() {
        return metadata;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        UpdateEntityChange that = (UpdateEntityChange) o;

        if (newEntity != that.newEntity) return false;
        if (entityId != null ? !entityId.equals(that.entityId) : that.entityId != null) return false;
        if (entityType != null ? !entityType.equals(that.entityType) : that.entityType != null) return false;
        if (propertyChanges != null ? !propertyChanges.equals(that.propertyChanges) : that.propertyChanges != null)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = entityType != null ? entityType.hashCode() : 0;
        result = 31 * result + (entityId != null ? entityId.hashCode() : 0);
        result = 31 * result + (newEntity ? 1 : 0);
        result = 31 * result + (propertyChanges != null ? propertyChanges.hashCode() : 0);
        return result;
    }
}
